package com.interview.a_多线程.h_多线程问题.b_找出累加错误_位置;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 并发累加
 * * <p>
 * * 找到错误的位置 并记录次数
 */
public class Test {

    public static void main(String[] args) throws InterruptedException {
        ThreadAdd add = new ThreadAdd();

        Thread thread1 = new Thread(add);
        thread1.start();

        Thread thread2 = new Thread(add);
        thread2.start();


        //        主线程 等待 子线程完成

        thread1.join();
        thread2.join();

        //
        System.out.println("count  实际结果 = " + add.count);

        System.out.println("count  正确的数量 = " + add.realCount);

        System.out.println("count  错误的数量 = " + add.errorCount);
    }
}

class ThreadAdd implements Runnable {
    public int count = 0;
    private boolean[] mark = new boolean[1000000];
    private CyclicBarrier cyclicBarrier1 = new CyclicBarrier(2);
    private CyclicBarrier cyclicBarrier2 = new CyclicBarrier(2);
    //
    AtomicInteger realCount = new AtomicInteger();
    //
    AtomicInteger errorCount = new AtomicInteger();

    @Override
    public void run() {
        mark[0] = true;

        for (int i = 0; i < 100000; i++) {
            try {
                //这两行是为了 让 count++出现可能出现并发
                cyclicBarrier2.reset();
                cyclicBarrier1.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

            count++;

            try {
                //这两行是为了 有可见性的count 在每个线程进入同步代码块时，，保持不变
                //改变线程的执行顺序
                cyclicBarrier1.reset();
                cyclicBarrier2.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

            realCount.incrementAndGet();
            synchronized (this) {
                if (mark[count] && mark[count - 1]) {
                    System.out.println("发生了错误，位置：" + count);
                    errorCount.incrementAndGet();
                }
                mark[count] = true;
            }

        }

    }
}
